<?php

class Bot
{
    /**
     * @var null|Bot
     */
    private static $instance = null;
    private static $lastId;

    private $redmineApi = null;
    private $cacheUsersToProjects = array();
    private $cacheUsers = array();
    private $cacheRedmineUsers = array();
    /**
     * @var null|PDO
     */
    private static $db = null;

    //типы действий
    const CREATE_ISSUE   = '!newtask'; // !newtask [Name]; [Description];           | !новая
    const CHANGE_PROJECT = '!changep'; // !changep [id]                             | !смпроект
    const ON_TEST        = '!ontest' ; // !ontest  [id]                             | !натест            ----issue_status_id //писать в скайп тестировщику номер задачи fs.QA
    const ASSIGN_USER    = '!assign' ; // !assign  [playformid]                     | !назначить
    const GET_MY_TASKS   = '!mytasks'; // !mytasks                                  | !мои
    const GET_TASK       = '!task'   ; // !task    [id]                             | !таск
    const GET_PROJECTS   = '!listp'  ; // !listp                                    | !проекты
    const CLOSE_ISSUE    = '!close'  ; // !close                                    | !закрыть
    const HELP           = '!help'   ; // !help                                     | !помощь
    const COMMENT        = '!comment'; // !comment [id]
    const PROJECT        = '!curp'   ; // !project [id]
    const EXIT_PROJECT   = '!exitp'  ; // !exitp
    const GET_CURRENT_PROJECT = '!getcurp';  //!getcurp
    const INSERT         = '!insert' ; //!insert
    const REGISTER       = '!reg'    ; //!reg [redmine]; [playform];
    const TESTING        = '!testing'; //!testing [Name]; [Description];
    const FIND_USER      = '!find'   ; //!find [Фамилия];

    //мапа для команд на русском языке
    private $mapCommands = array(
        self::CREATE_ISSUE   => '!новая',
        self::CHANGE_PROJECT => '!измпроект',
        self::ON_TEST        => '!натест' ,
        self::ASSIGN_USER    => '!назначить',
        self::GET_MY_TASKS   => '!мои',
        self::GET_TASK       => '!таск',
        self::GET_PROJECTS   => '!проекты',
        self::CLOSE_ISSUE    => '!закрыть',
        self::HELP           => '!помощь',
        self::COMMENT        => '!коммент',
        self::PROJECT        => '!текпроект',
        self::EXIT_PROJECT   => '!выхпроект'  ,
        self::GET_CURRENT_PROJECT => '!идтекпроект',
        self::INSERT         => '!вставить',
        self::REGISTER       => '!рег',
        self::TESTING        => '!новыйтест',
        self::FIND_USER      => '!поиск',

    );

    private $mapDescriptions = array(
        self::CREATE_ISSUE   => "Создать новую задачу в redmine. \n Пример: !newtask название; описание задачи \n",
        self::CHANGE_PROJECT => "Изменить проект у задачи. \n Синтаксис:!changep [id таска]; [id проекта]; \n",
        self::ON_TEST        => "Отправить задачу на тестирование. \n Пример: !ontest 7777 \n" ,
        self::ASSIGN_USER    => "Назначить человека на задачу. \n Пример: !assign 7777;lukmanov\n",
        self::GET_MY_TASKS   => "Получить список Мои задачи\n",
        self::GET_TASK       => "Получить таск по его id. \n Пример: !task 7777\n",
        self::GET_PROJECTS   => "Получить список всех проектов\n",
        self::CLOSE_ISSUE    => "Закрыть задачу. Пример: !close [id задачи]\n",
        self::HELP           => "Помощь. Пример: !help\n",
        self::COMMENT        => "Создание комментария к задаче. \n Пример: !comment 7777; комментарий\n",
        self::PROJECT        => "Установить текущий проект. Пример: !curp 21\n",
//        self::EXIT_PROJECT   => "Выйти из текущего проекта. Пример: !exitp \n"  ,
        self::GET_CURRENT_PROJECT => "Узнать в каком проекте ты сейчас находишься. Пример: !getcurp\n",
//        self::REGISTER       => "Указать боту необходимые для работы с ним данные.\n Синтаксис: !reg [login_redmine]; [login_playform]; \n Пример !reg ko4evnik;lukmanov\n",
        self::TESTING        => "Создаем задачу с трекером тестинг\n",
        self::FIND_USER      => "Получить информацию о сотруднике по его Фамилии. Пример: !find Лукманов\n",
    );

    /**
     * @static
     * @return Bot
     */
    public static function getInstance()
    {
        if (!self::$instance) {
            self::$instance = new Bot();
        }

        return self::$instance;
    }

    /**
     * @static
     * @return null|PDO
     */
    public function getDb()
    {
        if (!self::$db) {
            self::$db = new PDO('mysql:host=localhost;dbname=bot', 'bot', 'FElkgrJEIFje', array(PDO::ATTR_PERSISTENT => true));
        }

        return self::$db;
    }

    private function __construct()
    {
        $this->redmineApi = Api::factory('xml');//new RedmineApi();
        $selectRedmineUsers = $this->getDb()->query("SELECT * FROM `redmine_users`");
        $selectRedmineUsers->setFetchMode(PDO::FETCH_ASSOC);

        while($user = $selectRedmineUsers->fetch()) {
            $this->cacheRedmineUsers[$user['id_redmine']] = $user;
        }
    }

    public function insertUser($skype) {

    }

    public function getCurrentProject($userId)
    {
        if (!$userId) {
            return 0;
        }

        //сначала проверяем в кеше
        if (isset($this->cacheUsersToProjects[$userId])) {
            return $this->cacheUsersToProjects[$userId];
        }

        //если там нет то лезем в БД
        $selectLink = $this->getDb()->query('SELECT project_id FROM users_to_projects WHERE user_id = ' . $userId);
        $link = $selectLink->fetch(PDO::FETCH_ASSOC);
        $selectLink->closeCursor();

        //если в БД есть то положим в кеш и вернем
        if ($link) {
            $this->cacheUsersToProjects[$userId] = $link['project_id'];
            return $link['project_id'];
        }

        //если нет и там то возвращаем 0
        return 0;
    }



    public function getCurrentIssueId()
    {
        return $this->currentIssueId;
    }

    public function setCurrentProject($projectId, $userId)
    {
        if (!$projectId || !$userId) {
            return false;
        }

        if (!((int) $projectId)) {
            $projectId = $this->getProjectIdByName($projectId);

            if (!$projectId) {
                return false;
            }
        }



        if (!$this->redmineApi->isProject($projectId)) {
            return false;
        }

        $this->getDb()->exec('INSERT INTO `users_to_projects` (`project_id`, `user_id`) VALUES (' . $projectId . ', ' . $userId . ' ) ON DUPLICATE KEY UPDATE `project_id` = VALUES(`project_id`)' );
        $this->cacheUsersToProjects[$userId] = $projectId;
        return $this->cacheUsersToProjects[$userId];
    }

    public function setCurrentIssue($value)
    {
        //$this->currentIssueId = $value;
    }

    public function getCacheUsers($key = false)
    {
        if ($key === false) {
            return $this->cacheUsers;
        }

        $user = (isset($this->cacheUsers[$key]) && !empty($this->cacheUsers[$key])) ? $this->cacheUsers[$key] : array();
        return $user;
    }

    public static function getDetails($messageId)
    {
        global $n;
        var_dump('step 4');
        $ch    = $n->Invoke('GET CHATMESSAGE ' . $messageId . ' CHATNAME');
        $mess  = $n->Invoke('GET CHATMESSAGE ' . $messageId . ' BODY');
        $auth  = $n->Invoke('GET CHATMESSAGE ' . $messageId . ' FROM_DISPNAME');
        $login = $n->Invoke('GET CHATMESSAGE ' . $messageId . ' FROM_HANDLE');

        var_dump($ch, $auth, $login, $mess);

        /* Автора сообщения, id чата и текст сообщения.*/
        $author  = explode('FROM_DISPNAME ', $auth);
        $chat    = explode('CHATNAME ', $ch);
        $message = explode('BODY ', $mess);
        $skype   = explode('FROM_HANDLE', $login);

        if (isset($author[1]) AND isset($message[1])) {
            echo $author[1].': '.$message[1]."\n"; //Выводим в консоль автора и сообщение
        }
        var_dump($chat, $message, $messageId, $skype);

        /* вызываем обработку сообщения только когда оно начинается на "!" */
        if (isset($message[1]) &&  substr($message[1], 0, 1) == '!') {

            Bot::getInstance()->reply($chat[1], $message[1], $messageId, $skype[1]);
        }
    }

    public function reply($chat, $message, $id, $skype)
    {
        var_dump('step 5');
        $skype = trim($skype);
        global $n;
        var_dump('last message id:' . $id);

        //если id cообщения, на которое нужно ответить, меньше чем id предыдущего, то ответа не будет.
        if ($this->getLastId() < $id) {
            $reply = $this->getReply($message, $skype);

            if ($reply != '' || !empty($reply)) {
                $n->Invoke('CHATMESSAGE ' . $chat . ' ' . $reply); //Посылаем сообщение
            } else {
                $n->Invoke('CHATMESSAGE ' . $chat . ' Не знаю что ответить'); //Посылаем сообщение
                echo 'Не знаю что ответить.';
            }

            self::$lastId = $id;
            file_put_contents('last_id.txt', $id);
        } else {
            file_put_contents('log_double_message.txt', date('H-i-s') . ' - '. serialize($chat) . ' - '. serialize($message) . ' - '. serialize($id)  . ' - '. serialize($skype)  . "\n", FILE_APPEND);
            echo 'Уже отвечал' . "\n";
        }
    }

    public function getLastId()
    {
        if (!self::$lastId) {
            self::$lastId = file_get_contents('last_id.txt');
        }

        return self::$lastId;
    }

    public function getMsgParams($message)
    {
//        $params = preg_split('/\"(.+?)\"/', $message, -1, PREG_SPLIT_DELIM_CAPTURE);
//        preg_match_all('/\"(?:\\.|[^\\\"])*\"|\\S+/', $message, $params);
        $paramsFromMsg  = array();
        $expMsg = preg_split('# #', $message, 2);
        $command = $expMsg[0];
        $stringParams = isset($expMsg[1]) ? $expMsg[1] :  '' ;
        $params[0] = $command;

        if ($stringParams) {
            $paramsFromMsg = explode(';', $stringParams);
        }

        foreach ($paramsFromMsg as $paramFromMsg) {
            if (!empty($paramFromMsg)) {
                $paramFromMsg = trim($paramFromMsg);
            }
            $params[] = $paramFromMsg;
        }
        var_dump($params);

        return $params;
    }

    /**
     * @param $message
     * @param $skype
     * @return bool|string
     */
    public function actionCommand($message, $skype)
    {
        var_dump('step 7');
        $redmineApi = $this->redmineApi;
        $commands = $this->getMapCommands();
        $msgParams = $this->getMsgParams($message);
        $action = '';

        foreach ($commands as $command => $commandRus) {
            if (trim($msgParams[0]) == $command || trim($msgParams[0]) == $commandRus) {
                $action = $command;
                break;
            }
        }

        if (empty($action)) {
            return ' Команда не найдена. Чтобы просмотреть все доступные команды, используйте !help';
        }

        $user = $this->getInfoUserBySkype($skype);

        if (!$user && $action != self::REGISTER) {
            return 'Не могу ответить тебе, подаван. Обратитесь к Лукманову Роме.';//'Для дальнейшей работы нужно указать свои данные. Используйте команду: !reg [login_redmine]; [login_playform];';
        }

        $notes = "\n " . '  Автор изменений: ' . $user['name'] . ' (skype - ' . $user['skype'] . ')';

        switch ($action) {
            case self::HELP:
                $reply = $this->getHelp();
                break;
            case self::CREATE_ISSUE:
                $name        = isset($msgParams[1]) ? $msgParams[1] : '';
                $description = isset($msgParams[2]) ? $msgParams[2] : '';
                $projectId   = $this->getCurrentProject($user['id']);

                if ($projectId) {
                    $trackerId   = RedmineApi::TYPE_DEVELOP;
                    $description .= " \n\n ========================== \n Автор задачи: " . $user['name'] . " (Skype - " . $user['skype'] . ")\n";

                    $res = $redmineApi->createTask($name, $projectId, $description, $trackerId);
                    if ($res) {
                        $reply = 'Таск создан успешно. http://pm.vs58.net/issues/' . $res['issue']['id'];
                    } else {
                        $reply = 'Таск не создан. Попробуйте еще раз';
                    }
                } else {
                    $reply = 'Вы не зашли в проект. Используйте команду !curp [id-проекта].';
                }
                break;
            case self::TESTING:
                $name        = isset($msgParams[1]) ? $msgParams[1] : '';
                $description = isset($msgParams[2]) ? $msgParams[2] : '';
                $projectId   = $this->getCurrentProject($user['id']);
                $description .= " \n\n ========================== \n Автор задачи: " . $user['name'] . " (skype - " . $user['skype'] . ")\n";

                if ($projectId) {
                    $trackerId   = RedmineApi::TYPE_TESTING;
                    $res = $redmineApi->createTask($name, $projectId, $description, $trackerId);

                    if ($res) {
                        $reply = 'Таск создан успешно. http://pm.vs58.net/issues/' . $res['issue']['id'];
                    } else {
                        $reply = 'Таск не создан. Попробуйте еще раз';
                    }
                } else {
                    $reply = 'Вы не зашли в проект. Используйте команду !curp [id-проекта].';
                }
                break;
            case self::CHANGE_PROJECT:

                if ($redmineApi->changeProject($msgParams[1], $msgParams[2])) {
                    $reply = 'Изменен проект задачи.';
                } else {
                    $reply = 'Ошибка. Проект задачи не изменен.';
                }
                break;
            case self::CLOSE_ISSUE:
                $issueId = isset($msgParams[1]) ? intval($msgParams[1]) : false;
                $reply = 'Ошибка. Таск закрыть не получилось. попробуйте еще раз.';


                if ($issueId && $redmineApi->closeIssue($issueId, $notes)) {
                    $reply = 'Таск закрыт';
                }

                break;
            case self::ASSIGN_USER:
                $issueId  = isset($msgParams[1]) ? $msgParams[1] : '';
                $assignTo = isset($msgParams[2]) ? $msgParams[2] : '';


                $userPlayform = $assignTo;

                if (trim($assignTo) == 'me') {
                    $userPlayform = $user['playform'];
                }

                $reply = $this->assignTo($issueId, $userPlayform, $notes);

                break;
            case self::GET_MY_TASKS:
                $playform = isset($msgParams[1]) ? $msgParams[1] : '';
                $forUser = $user;

                if ($playform) {
                    $forUser = $this->getUserByPlayform($playform);
                }

                $redmineApi = Api::factory('json');
                $issues = $redmineApi->getUserIssues($forUser['id_redmine']);
                $reply = '';

                foreach ($issues as $issue) {
                    if (is_array($issue)) {

                        usort($issue, function ($a, $b) {
                            if ($a['status']['id'] == $b['tracker']['id']) {
                                return 0;
                            }

                            if ($a['status']['id'] > $b['tracker']['id']) {
                                return 1;
                            }

                            return -1;
                        });

                        usort($issue, function ($a, $b) {
                            if ($a['tracker']['id'] == $b['tracker']['id']) {
                                return 0;
                            }

                            if ($a['tracker']['id'] > $b['tracker']['id']) {
                                return 1;
                            }

                            return -1;
                        });
                        $reply .= 'Всего задач: ' . count($issue) . "\n";
                        foreach ($issue as $param) {
                            $reply .= "[" . $param['tracker']['name'] ." " . $param['id'] . "]\n --url: " . RedmineApi::DOMEN . 'issues/' . $param['id'] . "\n --Название: " .  $param['subject'] . "\n" . " --Статус: " . $param['status']['name'] . "\n";
                        }
                    }
                }

                $reply = ($issues) ? $reply : 'Нет задач';
                break;
            case self::GET_TASK:
                $id = (int) $msgParams[1];
                $reply = $this->getIssueById($id);
                break;
            case self::GET_PROJECTS:
                $reply = $this->getProjects();
                break;
            case self::ON_TEST:
                $issueId = isset($msgParams[1]) ? intval($msgParams[1]) : 0;
                $statusId = 8;

                if ($redmineApi->changeIssueStatus($issueId, $statusId, $notes)) {
                    $reply = 'Статус задачи изменен.';
                } else {
                    $reply = 'Ошибка. Не получилось изменить статус задачи.';
                }

                break;
            case self::COMMENT:
                $issueId = $msgParams[1];
                $comment = $msgParams[2];
                $comment .= " \n\n\n Автор комментария: " . $user['name'] . " (skype - " . $user['skype'] . ")\n";

                if ($redmineApi->changeComment($issueId, $comment)) {
                    $reply = 'Комментарий к задаче добавлен';
                } else {
                    $reply = 'Ошибка. Комментарий к задаче не добавлен.';
                }

                break;
            case self::PROJECT:
                $id = $msgParams[1];
                $setProject = $this->setCurrentProject($id, $user['id']);

                if ($setProject) {
                    $reply = 'Текущий проект изменен.';
                } else {
                    $reply = 'Текущий проект не был изменен.';
                }

                break;
            case self::GET_CURRENT_PROJECT:
                $id = $this->getCurrentProject($user['id']);
                $reply = 'Текущий проект не установлен';

                if ($id) {
                    $reply = 'Текущий проект  - ' . $id;
                }

                break;
            case self::EXIT_PROJECT:
//                $this->setCurrentProject();
                $reply = 'Не получилось выйти из текущего проекта';
                if (!$this->getCurrentProject($user['id'])) $reply = 'Вы вышли из проекта';
                break;
            case self::INSERT:
                $this->addUsersRedmine();
                $reply = 'База обновлена';
                break;
            case self::REGISTER:
                $redmine  = isset($msgParams[1]) ? $msgParams[1]: '';
                $playform = isset($msgParams[2]) ? $msgParams[2]: '';
                $reply = 'Введены неверные параметры. Попробуйте еще раз.';
                $result = $this->signUp($redmine, $playform, $skype);

                if ($result) {
                    $reply = $result;
                }
                break;
            case self::FIND_USER:
                $lastName = $msgParams[1];
                $reply = $this->findUser($lastName);

                if (!$reply) {
                    $reply = 'Пользователь не найден.';
                }

                break;
            default:
                $reply = 'Команда не найдена. Чтобы просмотреть все доступные команды, используйте !help';
                break;
        }
       // $this->callbackAction($paramsCallback);
        return $reply;
    }

    public function getHelp()
    {
        $help = '';
        foreach ($this->mapDescriptions as $command => $desc) {
            $russian = $this->mapCommands[$command];
            $help .= $command . '[' . $russian . ']' . ' - ' . $desc  . "\n";
        }
        return $help;
    }

    public function signUp($redmine, $playform, $skype)
    {
        if (!$redmine || !$playform || !$skype) {
            return false;
        }

        $playform = preg_replace('/@.*/', '', $playform);
        $selectUser = "SELECT `id` FROM `users` WHERE playform = '" . $playform . "'";
        $searchUser = $this->getDb()->query($selectUser);
        $res = false;

        // сначала проверим есть ли такой пользователь в табличке users
        if ($searchUser) {
            $res = $searchUser->fetch(PDO::FETCH_ASSOC);
            $searchUser->closeCursor();
        }

        //если нет то проверяем есть ли он в таблице users_redmine
        if (!$res) {
            $userRedmine = $this->getDb()->query("SELECT * FROM `redmine_users` where `redmine_login` LIKE '" . $redmine . "'");
            $redmineUser = false;

            if ($userRedmine) {
                $redmineUser = $userRedmine->fetch(PDO::FETCH_ASSOC);
                $userRedmine->closeCursor();
            }

            //если нет и там то отправляем к админу
            if (!$redmineUser) {
                return 'Вы не зарегистированы в системе redmine. Обратитесь к администратору.';
            } else {  //если есть то добавляем в БД и в кеш.
                $insert = 'INSERT INTO `users` (`skype`, `playform`, `redmine`) VALUES ("' . trim($skype) . '", "' . trim($playform) . '", ' . $redmineUser['id_redmine'] . ')';
                $this->getDb()->exec($insert);
                $insertId = $this->getDb()->lastInsertId();
                $user = array(
                    'id'            => $insertId,
                    'playform'      => $playform,
                    'id_redmine'    => $redmineUser['id_redmine'],
                    'skype'         => $skype,
                    'redmine_login' => $redmineUser['redmine_login']
                );

                $this->setCacheUsers($user);
                return 'Регистрация прошла успешно. Можете продолжать работу.';
            }
        } else {
            //проверяем какой логин редмайна сейчас соответствует этому плайформу
        }

        return false;
    }

    public function getMapCommands()
    {
        return $this->mapCommands;
    }

    /**
     * @param $msg
     * @param $skype
     * @return bool|string
     */
    public function getReply($msg, $skype)
    {
        var_dump('step 6');
        return $this->actionCommand($msg, $skype);
    }

    public function getInfoUserBySkype($login)
    {
        $user = array();
        $cacheUser = $this->getCacheUsers($login);
        file_put_contents('log_users_cache.txt', date('H-i-s') . ' - '. serialize($cacheUser) . ' - '. $login . "\n", FILE_APPEND);

        if (!$cacheUser) {
            $query = $this->getDb()->query("SELECT * FROM `users` INNER JOIN `redmine_users` ON `redmine_users`.`id_redmine` = `users`.`redmine` WHERE `users`.`skype` LIKE '" . trim($login) . "'");
            if ($query) {
                $userDb = $query->fetch(PDO::FETCH_ASSOC);
                $query->closeCursor();
            }

            if (isset($userDb)) {
                $this->setCacheUsers($userDb);
                $user = $userDb;
            }
        } else {
           $user = $cacheUser;
        }

        file_put_contents('log_users.txt', date('H-i-s') . ' - ' . serialize($cacheUser) . ' - ' . serialize(@$userDb) .' - '. $login . "\n", FILE_APPEND);

        if (!$user) {
            file_put_contents('log_users_fail.txt', date('H-i-s') . ' - ' . serialize($cacheUser) . ' - ' . serialize(@$userDb) .' - '. serialize(@$query) .' - '. $login . ' - ' . serialize($user) . "\n", FILE_APPEND);
        }

        return $user;
    }

    public function assignTo($issueId, $playform, $notes = '')
    {
        $assignUser = $this->getUserByPlayform($playform);

        //если и там нет то пишем что пользователь не найден
        if (empty($assignUser)) {

            return 'Такой пользователь не найден';
        }

        if ($this->redmineApi->assignTo($issueId, $assignUser['id_redmine'], $assignUser['redmine_login'], $notes)) {
            return 'Пользователь назначен';
        }

        return 'Не получилось назначить. Попробуйте еще раз';
    }

    public function sendNotifyToSkype($skype, $msg, $options = array())
    {
        if (!$skype) {
            return false;
        }

        global $n;

        if ($options) {
            if (isset($options['issue_id'])) {
                $msg .= "\n" . $this->getIssueById($options['issue_id']);
            }
        }

        switch ($skype) {
            case 'fs.QA':
                $chatName = '#ko4evnik_/$scrmer;fe95ef1b9ca34552';
                break;
            case 'fs.SVN':
                $chatName = '#ko4evnik_/$fsyoda;82085ea7ec29892c';
                break;
            default:
                $chat = $n->Invoke('CHAT CREATE ' . $skype);
                $chatId = explode(' ', $chat);
                $chatName = $chatId[1];
                break;
        }
        $res = $n->Invoke('CHATMESSAGE ' . $chatName . ' ' . $msg); //Посылаем сообщение
        var_dump($res);
        file_put_contents('logs/messages/log_message' . date('Y-m-d') . '.txt', date('H-i-s') . '  -  ' . $chatName . ' - ' . serialize($res) . "\n", FILE_APPEND);
    }

    public function setCacheUsers($users)
    {
        if (empty($users) ||
            !isset($users['skype'])||
            !isset($users['id'])||
            !isset($users['playform'])||
            !isset($users['id_redmine']) ||
            !isset($users['skype']) ||
            !isset($users['name']) ||
            !isset($users['redmine_login'])
        ) {
            return false;
        }

        $this->cacheUsers[$users['skype']] = array(
            'id'            => $users['id'],
            'playform'      => $users['playform'],
            'id_redmine'    => $users['id_redmine'],
            'name'    => $users['name'],
            'skype'         => $users['skype'],
            'redmine_login' => $users['redmine_login']
        );

        return true;
    }

    public function addUsersRedmine($lastId = 300)
    {
        for ($i = 1; $i <= $lastId; $i++) {
            $user = $this->redmineApi->getUser($i);

            if ($user && $user['user']['id'] && $user['user']['login']) {
                $this->insertRedmineUser($user['user']['id'], $user['user']['login']);
            }
        }
    }

    public function insertRedmineUser($id, $login)
    {
        if (!$id || !$login) {
            return false;
        }

        $query = 'INSERT IGNORE INTO `redmine_users` (`id_redmine`, `redmine_login`) VALUES (' . $id  . ', "' . $login . '")';
        $result = $this->getDb()->exec($query);

        if ($result && !array_key_exists($id, $this->cacheRedmineUsers)) {
            $this->cacheRedmineUsers[$id] = array(
                'id_redmine'    => $id,
                'redmine_login' => $login,
            );
        }

        return true;
    }

    public function callbackAction($params)
    {
        //вызывается после выполнения команды.

        // будет в нем параметр to_user то нужно будет отправлять сообщение еще и ему
        return false;
    }

    public function getProjects()
    {
        $reply = '';
        $projects = $this->redmineApi->getProjects();

        if (!$projects || empty($projects)) {
            return 'Проектов не найдено';
        }

        foreach ($projects['projects'] as $project) {
            $reply .=  $project['id'] . ' - ' . ' ' . $project['name']  . "\n";
        }

        return $reply;
    }

    public function getUserByPlayform($playform)
    {
        $playform = trim($playform);

        //ищем в кеше
        $users = $this->getCacheUsers();
        foreach ($users as $user) {
            if ($playform == $user['playform']) {
                return $user;
            }
        }

        //если нет то лезем в БД
        $query = $this->getDb()->query("SELECT * FROM `users` INNER JOIN `redmine_users` ON `redmine_users`.`id_redmine` = `users`.`redmine` WHERE `users`.`playform` LIKE '" . $playform . "'");

        if ($query) {
            $resultUser = $query->fetch(PDO::FETCH_ASSOC);
            $query->closeCursor();
        }

        if ($resultUser) {
            $this->setCacheUsers($resultUser);
            return $resultUser;
        }

        return null;
    }

    public function getUserByIdRedmine($id)
    {
        $users = $this->getCacheUsers();

        foreach ($users as $user) {
            if ($id == $user['id_redmine']) {
                return $user;
            }
        }

        //если нет то лезем в БД
        $query = $this->getDb()->query("SELECT * FROM `users` INNER JOIN `redmine_users` ON `redmine_users`.`id_redmine` = `users`.`redmine` WHERE `redmine_users`.`id_redmine` = " .(int) $id);

        if ($query) {
            $resultUser = $query->fetch(PDO::FETCH_ASSOC);
            $query->closeCursor();
        }

        if ($resultUser) {
            $this->setCacheUsers($resultUser);
            return $resultUser;
        }

        return null;
    }

    public function getUserByRedmineLogin($login)
    {
        $users = $this->getCacheUsers();

        foreach ($users as $user) {
            if ($login == $user['redmine_login']) {
                return $user;
            }
        }

        //если нет то лезем в БД
        $query = $this->getDb()->query("SELECT * FROM `users` INNER JOIN `redmine_users` ON `redmine_users`.`id_redmine` = `users`.`redmine` WHERE `users`.`playform` LIKE '" . $login . "'");

        if ($query) {
            $resultUser = $query->fetch(PDO::FETCH_ASSOC);
            $query->closeCursor();

            if ($resultUser) {
                $this->setCacheUsers($resultUser);
                return $resultUser;
            }
        }

        return null;
    }

    public function getUsers()
    {
        $query = $this->getDb()->query("SELECT * FROM `users` RIGHT JOIN `redmine_users` ON `redmine_users`.`id_redmine` = `users`.`redmine`");

        if ($query) {
            $resultUser = $query->fetchAll(PDO::FETCH_ASSOC);
            $query->closeCursor();
        }

        if ($resultUser) {
            return $resultUser;
        }

        return null;
    }

    public function execute($query)
    {
        return $this->getDb()->exec($query) || mysql_error();
    }

    public function getUserBySvn($svn)
    {
        if (!$svn) {
            return false;
        }

        $query = $this->getDb()->query("SELECT * FROM `users` WHERE `svn` = '" . $svn . "'");

        if ($query) {
            $result = $query->fetch(PDO::FETCH_ASSOC);
            $query->closeCursor();
            return $result;
        }

        return array();
    }

    public function getProjectIdByName($name)
    {
        $projects = $this->redmineApi->getProjects();

        if (!$projects || empty($projects)) {
            return false;
        }

        $id = false;
        foreach ($projects['projects'] as $project) {
            if ($name == $project['name']) {
                $id = $project['id'];
                break;
            }
        }

        return $id;
    }

    public function findUser($lastName)
    {
        $lastName = trim($lastName);
        $lastName = iconv('utf-8', 'windows-1251', $lastName);

        if (!$lastName || strlen($lastName) < 3) {
            return false;
        }

        $first = mb_strtoupper(substr($lastName, 0, 1));
        $last = substr($lastName, 1);
        $find = $first . $last;
        $find = iconv('windows-1251', 'utf-8', $find);
        $reply = '';
        $query = $this->getDb()->query("SELECT DISTINCT * FROM `users` INNER JOIN `redmine_users` ON `redmine_users`.`id_redmine` = `users`.`redmine`" .
            " WHERE `name` LIKE '%$find%' OR " .
            "`svn` LIKE '%$find%' OR " .
            "`redmine_login` LIKE '%$find%' OR " .
            "`playform` LIKE '%$find%' OR " .
            "`skype`    LIKE '%$find%'"
        );

        if ($query) {
            $redmineUsers = $query->fetchAll(PDO::FETCH_ASSOC);
            $query->closeCursor();
            $countUsers = count($redmineUsers);
            $reply .= 'По твоему запросу';
            $reply .= ($countUsers == 1) ? " найден 1 сотрудник \n" : ' найдено ' . $countUsers . " сотрудников\n";

            foreach ($redmineUsers as $user) {
                $reply .= "\n";
                $reply .=  $user['name'] . "\n";
                $reply .=  'svn     : '  . $user['svn'] . "\n";
                $reply .=  'skype   : '  . $user['skype'] . "\n";
                $reply .=  'redmine : '  . $user['redmine_login'] . "\n";
                $reply .=  'playform : ' . $user['playform'] . "\n";
                $reply .= '=======================================';
            }
        }

        if (!$reply) {
            file_put_contents('fail_find', date('H-i-s') . ' - ' . serialize($redmineUsers) . ' ' . serialize($find) . "\n", FILE_APPEND);
        }

        return $reply;
    }

    public function getIssueById($id)
    {
        $issue = $this->redmineApi->getIssueById($id);
        $reply = 'Задача не найдена!';

        if ($issue) {
            $reply  = 'Задача:  '  . RedmineApi::DOMEN . 'issues/'   . $id  . "\n";
            $reply .= 'Название: ' . $issue['issue']['subject']             . "\n";
            $reply .= 'Трекер: '   . $this->getTrackerText($issue['issue']['tracker']['name'])     . "\n";
            $reply .= 'Статус: '   . $issue['issue']['status']['name']      . "\n";
            $reply .= 'Назначен: ' . $issue['issue']['assigned_to']['name'] . "\n";
            $reply .= '==================' . "\n";

            if (strlen($issue['issue']['description'] < 100)) {
                $reply .=  $issue['issue']['description'] . "\n";
            }
        }

        return $reply;
    }

    public function getTrackerText($tracker)
    {
        $flag = '';

        switch ($tracker) {
            case 'Testing':
                $flag = '(flag:br)';
                break;
            case 'Complaint':
                $flag = '(flag:cn)';
                break;
            case 'Defect':
                $flag = '(flag:tj)';
                break;
        }

        $tracker .= ' ' . $flag;
        return $tracker;
    }

    /**
     *  тестовое соединение с БД. костыль, чтобы не рвалось соединение. запускается раз в минуту
     */
    public function pingQuery()
    {
        var_dump($this->getDb());
//        var_dump($result);
        var_dump('test_query - ' . date("H-i-s"));
    }
}
